package itdep.common.domain.hibernate;

import itdep.common.domain.Entity;
import itdep.common.domain.EntityFilter;
import itdep.common.resolver.Resolvable;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

/**
 * @author Ivan Khalopik
 * @version $Revision: 4 $ $Date: 2010-06-10 13:13:16 +0000 (Thu, 10 Jun 2010) $
 */
public class EntityFilterProcessor<PK extends Serializable, F extends EntityFilter<PK>>
		implements FilterProcessor<PK, F>, Resolvable<Class> {
	private static final String ID_PROPERTY = "id";
	private static final String DELETED_PROPERTY = "deletedAt";

	public Class getResolveKey() {
		return Entity.class;
	}

	public void process(DetachedCriteria criteria, F filter) {
		processWithAlias(criteria, filter, null);
		innerProcess(criteria, filter);
	}

	public void processWithAlias(final DetachedCriteria criteria, final F filter, final String alias) {
		//do nothing
	}

	protected void innerProcess(final DetachedCriteria criteria, final F filter) {
		if (filter.isExisting() != null) {
			if (filter.isExisting()) {
				criteria.add(Restrictions.isNull(DELETED_PROPERTY));
			} else {
				criteria.add(Restrictions.isNotNull(DELETED_PROPERTY));
			}
		}
		if (!CollectionUtils.isEmpty(filter.getIncludeKeys())) {
			final Set<PK> pkSet = new HashSet<PK>(filter.getIncludeKeys());
			pkSet.removeAll(filter.getExcludeKeys());
			criteria.add(Restrictions.in(ID_PROPERTY, pkSet));
		} else if (!CollectionUtils.isEmpty(filter.getExcludeKeys())) {
			criteria.add(Restrictions.not(Restrictions.in(ID_PROPERTY, filter.getExcludeKeys())));
		}
	}

	protected static String withAlias(final String alias, final String property) {
		return alias != null ? alias + "." + property : property;
	}
}
